package com.automotive.can1939.can;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import com.automotive.can1939.model.CanFrame;
import com.automotive.can1939.model.J1939Frame;
import com.automotive.can1939.jni.CanNativeInterface;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import timber.log.Timber;

/**
 * CAN通信管理器
 * 负责CAN数据的发送、接收和管理
 * 使用JNI与底层CAN驱动通信
 */
public class CanManager implements CanNativeInterface.CanDataCallback, CanNativeInterface.CanStatusCallback {
    private static final String TAG = "CanManager";
    private static CanManager instance;
    
    private Context context;
    private boolean isConnected = false;
    private ExecutorService executorService;
    private Handler mainHandler;
    
    // CAN数据监听器列表
    private final List<CanDataListener> dataListeners = new CopyOnWriteArrayList<>();
    private final List<CanStatusListener> statusListeners = new CopyOnWriteArrayList<>();
    
    // 接收到的CAN帧缓存
    private final List<CanFrame> receivedFrames = new ArrayList<>();
    private static final int MAX_FRAME_CACHE = 1000;
    
    // CAN设备配置
    private String canDevicePath = "/dev/can0";
    private int canBaudRate = 500000; // 500kbps
    
    private CanManager(Context context) {
        this.context = context.getApplicationContext();
        this.executorService = Executors.newCachedThreadPool();
        this.mainHandler = new Handler(Looper.getMainLooper());
        
        // 设置JNI回调
        CanNativeInterface.setDataCallback(this);
        CanNativeInterface.setStatusCallback(this);
    }
    
    public static synchronized CanManager getInstance(Context context) {
        if (instance == null) {
            instance = new CanManager(context);
        }
        return instance;
    }
    
    /**
     * 连接CAN总线
     */
    public void connect() {
        if (executorService == null || executorService.isShutdown()) {
            Timber.w("ExecutorService已关闭，无法连接CAN总线");
            return;
        }
        
        executorService.execute(() -> {
            try {
                // 初始化CAN接口
                int initResult = CanNativeInterface.initCan(canDevicePath, canBaudRate);
                if (initResult != CanNativeInterface.ErrorCode.SUCCESS) {
                    throw new RuntimeException("CAN初始化失败，错误码: " + initResult);
                }
                
                // 连接CAN总线
                int connectResult = CanNativeInterface.connectCan();
                if (connectResult != CanNativeInterface.ErrorCode.SUCCESS) {
                    throw new RuntimeException("CAN连接失败，错误码: " + connectResult);
                }
                
                // 启动数据接收
                int receiveResult = CanNativeInterface.startReceiving();
                if (receiveResult != CanNativeInterface.ErrorCode.SUCCESS) {
                    throw new RuntimeException("启动CAN数据接收失败，错误码: " + receiveResult);
                }
                
                isConnected = true;
                Timber.d("CAN总线连接成功");
                
                // 通知状态监听器
                mainHandler.post(() -> {
                    for (CanStatusListener listener : statusListeners) {
                        listener.onConnected();
                    }
                });
                
            } catch (Exception e) {
                Timber.e(e, "CAN总线连接失败");
                mainHandler.post(() -> {
                    for (CanStatusListener listener : statusListeners) {
                        listener.onError("连接失败: " + e.getMessage());
                    }
                });
            }
        });
    }
    
    /**
     * 断开CAN总线连接
     */
    public void disconnect() {
        // 只有在连接状态下才执行断开操作
        if (isConnected && executorService != null && !executorService.isShutdown()) {
            executorService.execute(() -> {
                try {
                    // 停止数据接收
                    CanNativeInterface.stopReceiving();
                    
                    // 断开CAN连接
                    CanNativeInterface.disconnectCan();
                    
                    isConnected = false;
                    Timber.d("CAN总线已断开");
                    
                    mainHandler.post(() -> {
                        for (CanStatusListener listener : statusListeners) {
                            listener.onDisconnected();
                        }
                    });
                    
                } catch (Exception e) {
                    Timber.e(e, "断开CAN连接时发生错误");
                }
            });
        }
    }
    
    /**
     * 发送CAN帧
     */
    public void sendFrame(CanFrame frame) {
        if (!isConnected) {
            Timber.w("CAN总线未连接，无法发送数据");
            return;
        }
        
        if (executorService == null || executorService.isShutdown()) {
            Timber.w("ExecutorService已关闭，无法发送数据");
            return;
        }
        
        executorService.execute(() -> {
            try {
                // 通过JNI发送CAN帧
                int result = CanNativeInterface.sendCanFrame(
                    frame.getCanId(),
                    frame.getData(),
                    frame.getDataLength(),
                    frame.isExtended()
                );
                
                if (result == CanNativeInterface.ErrorCode.SUCCESS) {
                    Timber.d("发送CAN帧成功: %s", frame.toString());
                    
                    // 通知发送成功
                    mainHandler.post(() -> {
                        for (CanDataListener listener : dataListeners) {
                            listener.onFrameSent(frame);
                        }
                    });
                } else {
                    throw new RuntimeException("发送CAN帧失败，错误码: " + result);
                }
                
            } catch (Exception e) {
                Timber.e(e, "发送CAN帧失败");
                mainHandler.post(() -> {
                    for (CanStatusListener listener : statusListeners) {
                        listener.onError("发送失败: " + e.getMessage());
                    }
                });
            }
        });
    }
    
    /**
     * 处理接收到的CAN数据（由JNI回调）
     */
    private void processReceivedData(CanFrame frame) {
        // 添加到缓存
        synchronized (receivedFrames) {
            receivedFrames.add(frame);
            if (receivedFrames.size() > MAX_FRAME_CACHE) {
                receivedFrames.remove(0);
            }
        }
        
        // 检查是否为J1939协议（29位扩展ID）
        if (frame.isExtended() && isJ1939Frame(frame)) {
            // 转换为J1939帧并通知监听器
            J1939Frame j1939Frame = new J1939Frame(frame.getCanId(), frame.getData());
            mainHandler.post(() -> {
                for (CanDataListener listener : dataListeners) {
                    listener.onJ1939DataReceived(j1939Frame);
                }
            });
        } else {
            // 通知传统CAN监听器
            mainHandler.post(() -> {
                for (CanDataListener listener : dataListeners) {
                    listener.onFrameReceived(frame);
                }
            });
        }
    }
    
    /**
     * 添加数据监听器
     */
    public void addDataListener(CanDataListener listener) {
        dataListeners.add(listener);
    }
    
    /**
     * 移除数据监听器
     */
    public void removeDataListener(CanDataListener listener) {
        dataListeners.remove(listener);
    }
    
    /**
     * 添加状态监听器
     */
    public void addStatusListener(CanStatusListener listener) {
        statusListeners.add(listener);
    }
    
    /**
     * 移除状态监听器
     */
    public void removeStatusListener(CanStatusListener listener) {
        statusListeners.remove(listener);
    }
    
    /**
     * 获取连接状态
     */
    public boolean isConnected() {
        return isConnected;
    }
    
    /**
     * 获取接收到的帧列表
     */
    public List<CanFrame> getReceivedFrames() {
        synchronized (receivedFrames) {
            return new ArrayList<>(receivedFrames);
        }
    }
    
    /**
     * 清空接收缓存
     */
    public void clearReceivedFrames() {
        synchronized (receivedFrames) {
            receivedFrames.clear();
        }
    }
    
    /**
     * 检查是否为J1939帧
     * J1939使用29位扩展CAN ID，且通常PGN在有效范围内
     */
    private boolean isJ1939Frame(CanFrame frame) {
        if (!frame.isExtended()) {
            return false;
        }
        
        // 提取PGN（参数组号）
        int canId = frame.getCanId();
        int pgn = (canId >> 8) & 0x3FFFF; // 提取PGN部分
        
        // 检查是否在J1939 PGN有效范围内
        return pgn >= 0x00F000 && pgn <= 0x00FFFF || // 标准PGN范围
               pgn >= 0x00EF00 && pgn <= 0x00EFFF;   // 专有PGN范围
    }
    
    /**
     * 发送J1939帧
     */
    public void sendJ1939Frame(J1939Frame frame) {
        if (!isConnected) {
            Timber.w("CAN总线未连接，无法发送J1939数据");
            return;
        }
        
        try {
            // 转换为标准CAN帧发送
            CanFrame canFrame = frame.toCanFrame();
            sendFrame(canFrame);
        } catch (Exception e) {
            Timber.e(e, "发送J1939帧失败");
        }
    }
    
    /**
     * 设置CAN设备配置
     */
    public void setCanConfig(String devicePath, int baudRate) {
        this.canDevicePath = devicePath;
        this.canBaudRate = baudRate;
    }
    
    /**
     * 设置CAN过滤器
     */
    public void setCanFilter(int filterId, int mask) {
        if (isConnected && executorService != null && !executorService.isShutdown()) {
            executorService.execute(() -> {
                int result = CanNativeInterface.setCanFilter(filterId, mask);
                if (result != CanNativeInterface.ErrorCode.SUCCESS) {
                    Timber.w("设置CAN过滤器失败，错误码: %d", result);
                }
            });
        }
    }
    
    /**
     * 释放资源
     */
    public void release() {
        // 先断开连接但不关闭线程池
        if (isConnected) {
            try {
                // 停止数据接收
                CanNativeInterface.stopReceiving();
                
                // 断开CAN连接
                CanNativeInterface.disconnectCan();
                
                isConnected = false;
                Timber.d("CAN总线已断开");
                
                // 通知状态监听器
                mainHandler.post(() -> {
                    for (CanStatusListener listener : statusListeners) {
                        listener.onDisconnected();
                    }
                });
            } catch (Exception e) {
                Timber.e(e, "断开CAN总线连接时发生错误");
            }
        }
        
        // 释放JNI资源
        try {
            if (executorService != null && !executorService.isShutdown()) {
                executorService.execute(() -> {
                    CanNativeInterface.releaseCan();
                });
                
                // 关闭线程池
                executorService.shutdown();
                try {
                    // 等待所有任务完成
                    if (!executorService.awaitTermination(2, TimeUnit.SECONDS)) {
                        executorService.shutdownNow();
                    }
                } catch (InterruptedException e) {
                    executorService.shutdownNow();
                    Thread.currentThread().interrupt();
                }
            }
        } catch (Exception e) {
            Timber.e(e, "释放CAN资源时发生错误");
        }
        
        dataListeners.clear();
        statusListeners.clear();
    }
    
    // ========== JNI回调接口实现 ==========
    
    /**
     * JNI回调：接收到CAN数据
     */
    @Override
    public void onCanDataReceived(int canId, byte[] data, int dataLength, boolean isExtended, long timestamp) {
        try {
            // 创建CAN帧对象
            CanFrame frame = new CanFrame(canId, data, isExtended);
            frame.setTimestamp(timestamp);
            frame.setDataLength(dataLength);
            
            // 处理接收到的数据
            processReceivedData(frame);
            
        } catch (Exception e) {
            Timber.e(e, "处理接收到的CAN数据时发生错误");
        }
    }
    
    /**
     * JNI回调：CAN状态变化
     */
    @Override
    public void onCanStatusChanged(int status, String message) {
        mainHandler.post(() -> {
            switch (status) {
                case CanNativeInterface.StatusCode.CONNECTED:
                    isConnected = true;
                    for (CanStatusListener listener : statusListeners) {
                        listener.onConnected();
                    }
                    break;
                    
                case CanNativeInterface.StatusCode.DISCONNECTED:
                    isConnected = false;
                    for (CanStatusListener listener : statusListeners) {
                        listener.onDisconnected();
                    }
                    break;
                    
                case CanNativeInterface.StatusCode.ERROR:
                    for (CanStatusListener listener : statusListeners) {
                        listener.onError(message);
                    }
                    break;
                    
                default:
                    Timber.w("未知的CAN状态码: %d, 消息: %s", status, message);
                    break;
            }
        });
    }
    
    /**
     * CAN数据监听器接口
     */
    public interface CanDataListener {
        void onFrameReceived(CanFrame frame);
        void onFrameSent(CanFrame frame);
        void onJ1939DataReceived(J1939Frame frame);
    }
    
    /**
     * CAN状态监听器接口
     */
    public interface CanStatusListener {
        void onConnected();
        void onDisconnected();
        void onError(String error);
    }
}